home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr07 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / decompile.c < prev    next >
C/C++ Source or Header  |  1993-03-29  |  19KB  |  845 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "global.h"
  20. #include "decompile.h"
  21. #include "eval.h"
  22. #include "cell.h"
  23. #include "io-utils.h"
  24.  
  25.  
  26.  
  27. struct pr_node
  28.   {
  29.     int tightness;
  30.     int len;
  31.     char string[1];
  32.   };
  33.  
  34.  
  35. static VOIDSTAR save_decomp;
  36. static CELLREF decomp_row;
  37. static CELLREF decomp_col;
  38.  
  39. /* These #defines are so that we don't have to duplicate code below */
  40. /* JF: now obsolete, and should be trashed. */
  41.  
  42. #define F0    a0?"@%s()":"%s()"
  43. #define F1    a0?"@%s(%s)":"%s(%s)"
  44. #define F2    a0?"@%s(%s, %s)":"%s(%s, %s)"
  45. #define F3    a0?"@%s(%s, %s, %s)":"%s(%s, %s, %s)"
  46. #define F4    a0?"@%s(%s, %s, %s, %s)":"%s(%s, %s, %s, %s)"
  47. #define FN1    a0?"@%s(%s":"%s(%s"
  48.  
  49. /* We decompile things with these wierd node-things.  It's ugly, but it works.
  50.  */
  51. #ifdef __STDC__
  52. static struct pr_node *
  53. n_alloc (int size, int tightness, char *fmt,...)
  54. #else
  55. static struct pr_node *
  56. n_alloc (size, tightness, fmt, va_alist)
  57.      int size;
  58.      int tightness;
  59.      char *fmt;
  60.      va_dcl
  61. #endif
  62. {
  63.   struct pr_node *ret;
  64.   va_list args;
  65.  
  66.   ret = ck_malloc (sizeof (struct pr_node) + size + 1);
  67.   ret->len = size;
  68.   ret->tightness = tightness;
  69.   var_start (args, fmt);
  70.   vsprintf (ret->string, fmt, args);
  71.   va_end (args);
  72.   return ret;
  73. }
  74.  
  75. #define n_free(x)    free(x)
  76.  
  77. static struct pr_node *
  78. byte_decompile (expr)
  79.      unsigned char *expr;
  80. {
  81.   unsigned char byte;
  82.   double tmp_flt;
  83.   long tmp_lng;
  84.   char *tmp_str;
  85.   struct var *v;
  86.   unsigned long_skp;
  87.   unsigned char save_val;
  88.   unsigned jumpto;
  89.  
  90.   struct pr_node *new = 0;
  91.   int pri;
  92.   int aso;
  93.   char *chr;
  94.  
  95.   static struct pr_node **the_line;
  96.   static int line_alloc;
  97.  
  98.   static struct pr_node **c_node;
  99.   struct function *f;
  100.  
  101.   if (!the_line)
  102.     {
  103.       the_line = (struct pr_node **) ck_malloc (20 * sizeof (struct pr_node *));
  104.       line_alloc = 20;
  105.       c_node = the_line;
  106.     }
  107.  
  108. #ifdef TEST
  109.   if (!expr)
  110.     panic ("No expression to decompile");
  111. #endif
  112. next_byte:
  113.   byte = *expr++;
  114.   if (byte < USR1)
  115.     f = &the_funs[byte];
  116.   else if (byte < SKIP)
  117.     {
  118.       tmp_lng = *expr++;
  119.       f = &usr_funs[byte - USR1][tmp_lng];
  120.     }
  121.   else
  122.     f = &skip_funs[byte - SKIP];
  123.  
  124.   if (f->fn_argn & X_J)
  125.     jumpto = *expr++;
  126.   else if (f->fn_argn & X_JL)
  127.     {
  128.       jumpto = expr[0] + ((unsigned) (expr[1]) << 8);
  129.       expr += 2;
  130.     }
  131.   else
  132.     jumpto = 0;
  133.  
  134.   switch (GET_COMP (f->fn_comptype))
  135.     {
  136.     case C_IF:
  137.       if (expr[jumpto - 2] != SKIP)
  138.     {
  139.       long_skp = 1;
  140.       save_val = expr[jumpto - 3];
  141.       expr[jumpto - 3] = 0;
  142.     }
  143.       else
  144.     {
  145.       long_skp = 0;
  146.       save_val = expr[jumpto - 2];
  147.       expr[jumpto - 2] = 0;
  148.     }
  149.       c_node[0] = byte_decompile (expr);
  150.       c_node++;
  151.  
  152.       if (long_skp)
  153.     {
  154.       expr[jumpto - 3] = save_val;
  155.       expr += jumpto;
  156.       jumpto = expr[-2] + ((unsigned) (expr[-1]) << 8);
  157.     }
  158.       else
  159.     {
  160.       expr[jumpto - 2] = save_val;
  161.       expr += jumpto;
  162.       jumpto = expr[-1];
  163.     }
  164.       save_val = expr[jumpto];
  165.       expr[jumpto] = 0;
  166.       c_node[0] = byte_decompile (expr);
  167.       c_node -= 2;
  168.       expr[jumpto] = save_val;
  169.       expr += jumpto;
  170.       if (byte == IF || byte == IF_L)
  171.     {
  172.       if (c_node[0]->tightness <= 1)
  173.         new = n_alloc (8 + c_node[0]->len + c_node[1]->len + c_node[2]->len,
  174.                1,
  175.                "(%s) ? %s : %s", c_node[0]->string, c_node[1]->string, c_node[2]->string);
  176.       else
  177.         new = n_alloc (6 + c_node[0]->len + c_node[1]->len + c_node[2]->len,
  178.                1,
  179.                "%s ? %s : %s", c_node[0]->string, c_node[1]->string, c_node[2]->string);
  180.     }
  181.       else
  182.     new = n_alloc (6 + c_node[0]->len + c_node[1]->len + c_node[2]->len + strlen (f->fn_str),
  183.                1000,
  184.                F3, f->fn_str, c_node[0]->string, c_node[1]->string, c_node[2]->string);
  185.       n_free (c_node[0]);
  186.       n_free (c_node[1]);
  187.       n_free (c_node[2]);
  188.       break;
  189.  
  190.     case C_ANDOR:
  191.       save_val = expr[jumpto];
  192.       expr[jumpto] = 0;
  193.       c_node[0] = byte_decompile (expr);
  194.       expr[jumpto] = save_val;
  195.       expr += jumpto;
  196.       c_node++;
  197.       if (ISINFIX (f->fn_comptype))
  198.     {
  199.       pri = GET_IN (f->fn_comptype);
  200.       aso = GET_ASO (f->fn_comptype);
  201.       chr = f->fn_str;
  202.       goto do_infix;
  203.     }
  204.       else
  205.     goto do_fn2;
  206.  
  207.     case C_STR:
  208.       tmp_str = backslash_a_string ((char *) expr + jumpto, 1);
  209.       new = n_alloc (strlen (tmp_str) + 1,
  210.              1000,
  211.              tmp_str);
  212.       break;
  213.  
  214.     case C_CELL:
  215.       {
  216.     int num1, num2;
  217.     char *str;
  218.     CELLREF row, col;
  219.  
  220.     row = GET_ROW (expr);
  221.     col = GET_COL (expr);
  222.     expr += EXP_ADD;
  223.  
  224.     if (a0)
  225.       {
  226.         new = n_alloc (30, 1000, f->fn_str, col_to_str (col), row);
  227.       }
  228.     else
  229.       {
  230.         if (byte & ROWREL)
  231.           {
  232.         num1 = row - decomp_row;
  233.         if (byte & COLREL)
  234.           {
  235.             num2 = col - decomp_col;
  236.             if (row == decomp_row && col == decomp_col)
  237.               str = "rc";
  238.             else if (row == decomp_row)
  239.               {
  240.             str = "rc[%+d]";
  241.             num1 = num2;
  242.               }
  243.             else if (col == decomp_col)
  244.               str = "r[%+d]c";
  245.             else
  246.               str = "r[%+d]c[%+d]";
  247.           }
  248.         else if (row == decomp_row)
  249.           {
  250.             str = "rc%u";
  251.             num1 = num2 = col;
  252.           }
  253.         else
  254.           {
  255.             str = "r[%+d]c%u";
  256.             num2 = col;
  257.           }
  258.           }
  259.         else if (byte & COLREL)
  260.           {
  261.         num1 = row;
  262.         num2 = col - decomp_col;
  263.         if (col == decomp_col)
  264.           str = "r%uc";
  265.         else
  266.           str = "r%uc[%+d]";
  267.           }
  268.         else
  269.           {
  270.         str = "r%uc%u";
  271.         num1 = row;
  272.         num2 = col;
  273.           }
  274.         new = n_alloc (30, 1000, str, num1, num2);
  275.       }
  276.     new->len = strlen (new->string);
  277.       }
  278.       break;
  279.  
  280.     case C_RANGE:
  281.       {
  282.     char tmprbuf[40];
  283.     char tmpcbuf[40];
  284.     struct rng rng;
  285.  
  286.     GET_RNG (expr, &rng);
  287.     expr += EXP_ADD_RNG;
  288.  
  289.     if (a0)
  290.       new = n_alloc (40, 1000, f->fn_str, col_to_str (rng.lc), rng.lr, col_to_str (rng.hc), rng.hr);
  291.     else
  292.       {
  293.         /* Check for special cases */
  294.         if (rng.lr == rng.hr && ((byte & LRREL) ? 1 : 0) == ((byte & HRREL) ? 1 : 0))
  295.           {
  296.         if (byte & LRREL)
  297.           {
  298.             if (rng.lr == decomp_row)
  299.               {
  300.             tmprbuf[0] = 'r';
  301.             tmprbuf[1] = '\0';
  302.               }
  303.             else
  304.               (void) sprintf (tmprbuf, "r[%+d]", rng.lr - decomp_row);
  305.           }
  306.         else
  307.           sprintf (tmprbuf, "r%u", rng.lr);
  308.           }
  309.         else if ((byte & LRREL) && (byte & HRREL))
  310.           {
  311.         int r1, r2, rtmp;
  312.  
  313.         r1 = rng.lr - decomp_row;
  314.         r2 = rng.hr - decomp_row;
  315.         if (r1 < r2)
  316.           rtmp = r1, r1 = r2, r2 = rtmp;
  317.         (void) sprintf (tmprbuf, "r[%+d:%+d]", r1, r2);
  318.           }
  319.         else if ((byte & LRREL))
  320.           (void) sprintf (tmprbuf, "r[%+d]:%u", rng.lr - decomp_row, rng.hr);
  321.         else if (byte & HRREL)
  322.           (void) sprintf (tmprbuf, "r%u:[%+d]", rng.lr, rng.hr - decomp_row);
  323.         else if (rng.lr < rng.hr)
  324.           (void) sprintf (tmprbuf, "r%u:%u", rng.lr, rng.hr);
  325.         else
  326.           (void) sprintf (tmprbuf, "r%u:%u", rng.hr, rng.lr);
  327.  
  328.         if (rng.lc == rng.hc && ((byte & LCREL) ? 1 : 0) == ((byte & HCREL) ? 1 : 0))
  329.           {
  330.         if (byte & LCREL)
  331.           {
  332.             if (rng.lc == decomp_col)
  333.               {
  334.             tmpcbuf[0] = 'c';
  335.             tmpcbuf[1] = '\0';
  336.               }
  337.             else
  338.               sprintf (tmpcbuf, "c[%+d]", rng.lc - decomp_col);
  339.           }
  340.         else
  341.           sprintf (tmpcbuf, "c%u", rng.lc);
  342.           }
  343.         else if ((byte & LCREL) && (byte & HCREL))
  344.           {
  345.         int c1, c2, ctmp;
  346.  
  347.         c1 = rng.lc - decomp_col;
  348.         c2 = rng.hc - decomp_col;
  349.         if (c1 < c2)
  350.           ctmp = c1, c1 = c2, c2 = ctmp;
  351.         (void) sprintf (tmpcbuf, "c[%+d:%+d]", c1, c2);
  352.           }
  353.         else if ((byte & LCREL))
  354.           (void) sprintf (tmpcbuf, "c[%+d]:%u", rng.lc - decomp_col, rng.hc);
  355.         else if (byte & HCREL)
  356.           (void) sprintf (tmpcbuf, "c%u:[%+d]", rng.lc, rng.hc - decomp_col);
  357.         else if (rng.lc < rng.hc)
  358.           (void) sprintf (tmpcbuf, "c%u:%u", rng.lc, rng.hc);
  359.         else
  360.           (void) sprintf (tmpcbuf, "c%u:%u", rng.hc, rng.lc);
  361.  
  362.         new = n_alloc (40, 1000, "%s%s", tmprbuf, tmpcbuf);
  363.       }
  364.     new->len = strlen (new->string);
  365.       }
  366.       break;
  367.  
  368.     case C_CONST:
  369.       new = n_alloc (strlen (f->fn_str) + 1, 1000, f->fn_str);
  370.       break;
  371.  
  372.     case C_FN0:
  373.     case C_FN0X:
  374.     case C_FN0 | C_T:
  375.       new = n_alloc (strlen (f->fn_str) + 3,
  376.              1000,
  377.              F0,
  378.              f->fn_str);
  379.       break;
  380.  
  381.     case C_FN1:
  382.       --c_node;
  383.       new = n_alloc (c_node[0]->len + strlen (f->fn_str) + 3,
  384.              1000,
  385.              F1, f->fn_str, c_node[0]->string);
  386.       n_free (*c_node);
  387.       break;
  388.  
  389.     case C_UNA:
  390.       --c_node;
  391.       if (c_node[0]->tightness < 9)
  392.     {
  393.       new = n_alloc (3 + c_node[0]->len,
  394.              9,
  395.              "%s(%s)", f->fn_str, c_node[0]->string);
  396.     }
  397.       else
  398.     {
  399.       new = n_alloc (1 + c_node[0]->len,
  400.              9,
  401.              "%s%s", f->fn_str, c_node[0]->string);
  402.     }
  403.       n_free (*c_node);
  404.       break;
  405.  
  406.     case C_INF:
  407.       pri = GET_IN (f->fn_comptype);
  408.       aso = GET_ASO (f->fn_comptype);
  409.       chr = f->fn_str;
  410.  
  411.     do_infix:
  412.       c_node -= 2;
  413.       if (c_node[0]->tightness < pri || (c_node[0]->tightness == pri && aso != 1))
  414.     {
  415.       if (c_node[1]->tightness < pri || (c_node[1]->tightness == pri && aso != -1))
  416.         new = n_alloc (7 + c_node[0]->len + c_node[1]->len,
  417.                pri,
  418.          "(%s) %s (%s)", c_node[0]->string, chr, c_node[1]->string);
  419.       else
  420.         new = n_alloc (5 + c_node[0]->len + c_node[1]->len,
  421.                pri,
  422.            "(%s) %s %s", c_node[0]->string, chr, c_node[1]->string);
  423.     }
  424.       else if (c_node[1]->tightness < pri || (c_node[1]->tightness == pri && aso != -1))
  425.     new = n_alloc (5 + c_node[0]->len + c_node[1]->len,
  426.                pri,
  427.            "%s %s (%s)", c_node[0]->string, chr, c_node[1]->string);
  428.       else
  429.     new = n_alloc (3 + c_node[0]->len + c_node[1]->len,
  430.                pri,
  431.              "%s %s %s", c_node[0]->string, chr, c_node[1]->string);
  432.  
  433.       n_free (c_node[0]);
  434.       n_free (c_node[1]);
  435.       break;
  436.  
  437.     case C_FN2:
  438.     do_fn2:
  439.       c_node -= 2;
  440.       new = n_alloc (c_node[0]->len + c_node[1]->len + strlen (f->fn_str) + 5,
  441.              1000,
  442.              F2, f->fn_str, c_node[0]->string, c_node[1]->string);
  443.       n_free (c_node[0]);
  444.       n_free (c_node[1]);
  445.       break;
  446.  
  447.     case C_FN3:
  448.       c_node -= 3;
  449.       new = n_alloc (c_node[0]->len + c_node[1]->len + c_node[2]->len + strlen (f->fn_str) + 7,
  450.              1000,
  451.              F3,
  452.              f->fn_str,
  453.              c_node[0]->string,
  454.              c_node[1]->string,
  455.              c_node[2]->string);
  456.       n_free (c_node[0]);
  457.       n_free (c_node[1]);
  458.       n_free (c_node[2]);
  459.       break;
  460.  
  461.     case C_FNN:
  462.       aso = *expr++;
  463.       c_node -= aso;
  464.  
  465.       if (aso == 1)
  466.     new = n_alloc (3 + c_node[0]->len + strlen (f->fn_str),
  467.                1000,
  468.                F1, f->fn_str, c_node[0]->string);
  469.       else
  470.     {
  471.       new = n_alloc (2 + c_node[0]->len + strlen (f->fn_str),
  472.              1000,
  473.              FN1, f->fn_str, c_node[0]->string);
  474.       --aso;
  475.       for (pri = 1; pri < aso; pri++)
  476.         {
  477.           n_free (c_node[0]);
  478.           c_node[0] = new;
  479.           new = n_alloc (2 + new->len + c_node[pri]->len,
  480.                  1000,
  481.                  "%s, %s", new->string, c_node[pri]->string);
  482.         }
  483.       n_free (c_node[0]);
  484.       c_node[0] = new;
  485.       new = n_alloc (3 + new->len + c_node[aso]->len,
  486.              1000,
  487.              "%s, %s)", new->string, c_node[aso]->string);
  488.     }
  489.       n_free (c_node[0]);
  490.       break;
  491.  
  492.     case C_FN4:
  493.       c_node -= 4;
  494.       new = n_alloc (c_node[0]->len + c_node[1]->len + c_node[2]->len + c_node[3]->len + strlen (f->fn_str) + 6,
  495.              1000,
  496.              F4,
  497.              f->fn_str,
  498.              c_node[0]->string,
  499.              c_node[1]->string,
  500.              c_node[2]->string,
  501.              c_node[3]->string);
  502.       n_free (c_node[0]);
  503.       n_free (c_node[1]);
  504.       n_free (c_node[2]);
  505.       n_free (c_node[3]);
  506.       break;
  507.  
  508.     case C_ERR:
  509.       tmp_str = (char *) expr + jumpto;
  510.       expr++;
  511.       new = n_alloc (strlen (tmp_str) + 1, 1000, tmp_str);
  512.       /* bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_str,sizeof(char *));
  513.         expr+=sizeof(char *);
  514.         new=n_alloc(strlen(tmp_str)+1,1000,f->fn_str,tmp_str); */
  515.       break;
  516.  
  517.     case C_FLT:
  518.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_flt, sizeof (double));
  519.       expr += sizeof (double);
  520.       new = n_alloc (20, 1000, f->fn_str, tmp_flt);
  521.       new->len = strlen (new->string);
  522.       break;
  523.  
  524.     case C_INT:
  525.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_lng, sizeof (long));
  526.       expr += sizeof (long);
  527.       new = n_alloc (20, 1000, f->fn_str, tmp_lng);
  528.       new->len = strlen (new->string);
  529.       break;
  530.  
  531.     case C_VAR:
  532.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & v, sizeof (struct var *));
  533.       expr += sizeof (struct var *);
  534.       new = n_alloc (strlen (v->var_name) + 1,
  535.              1000,
  536.              f->fn_str, v->var_name);
  537.       break;
  538.  
  539.  
  540.     default:
  541.       panic ("Bad decompile %d", f->fn_comptype);
  542.     }
  543.   *c_node++ = new;
  544.   if (c_node == &the_line[line_alloc])
  545.     {
  546.       line_alloc *= 2;
  547.       the_line = ck_realloc (the_line, line_alloc * sizeof (struct pr_node *));
  548.       c_node = &the_line[line_alloc / 2];
  549.     }
  550.  
  551.   if (*expr)
  552.     goto next_byte;
  553.  
  554.   /* if(c_node != &the_line[1]) {
  555.         io_error_msg("%d values on decompile stack!",c_node - the_line);
  556.         return the_line[0];
  557.     } */
  558.   new = *--c_node;
  559.   /* free(the_line); */
  560.   return new;
  561. }
  562.  
  563. /* Actual entry points to this file */
  564. /* decomp(row, col, cell) returns a string that can be byte_compiled to create
  565.    cell->formula  decomp_free() frees up the allocated string */
  566. #if __STDC__
  567. char *
  568. decomp (CELLREF r, CELLREF c, CELL *cell)
  569. #else
  570. char *
  571. decomp (r, c, cell)
  572.      CELLREF r;
  573.      CELLREF c;
  574.      CELL *cell;
  575. #endif
  576. {
  577.   struct pr_node *ret;
  578.   char *str;
  579.   extern char *bname[];
  580.  
  581.   if (!cell)
  582.     return "";
  583.   decomp_row = r;
  584.   decomp_col = c;
  585.   if (cell->cell_formula == 0)
  586.     {
  587.       switch (GET_TYP (cell))
  588.     {
  589.     case 0:
  590.       str = ck_malloc (1);
  591.       str[0] = '\0';
  592.       break;
  593.     case TYP_FLT:
  594.       str = strdup (flt_to_str (cell->cell_flt));
  595.       break;
  596.     case TYP_INT:
  597.       str = ck_malloc (20);
  598.       sprintf (str, "%ld", cell->cell_int);
  599.       break;
  600.     case TYP_STR:
  601.       str = strdup (backslash_a_string (cell->cell_str, 1));
  602.       break;
  603.     case TYP_BOL:
  604.       str = strdup (bname[cell->cell_bol]);
  605.       break;
  606.     case TYP_ERR:
  607.       str = strdup (ename[cell->cell_bol]);
  608.       break;
  609.     default:
  610.       str = 0;
  611. #ifdef TEST
  612.       panic ("Unknown type %d in decomp", GET_TYP (cell));
  613. #endif
  614.     }
  615.       save_decomp = (VOIDSTAR) str;
  616.       return str;
  617.     }
  618.   else
  619.     ret = byte_decompile (cell->cell_formula);
  620.   save_decomp = (VOIDSTAR) ret;
  621.   return &(ret->string[0]);
  622. }
  623.  
  624. #ifdef __STDC__
  625. void
  626. decomp_free (void)
  627. #else
  628. void
  629. decomp_free ()
  630. #endif
  631. {
  632. #ifdef TEST
  633.   if (!save_decomp)
  634.     panic ("No save decomp");
  635.   n_free (save_decomp);
  636.   save_decomp = (VOIDSTAR) 0;
  637. #else
  638.   n_free (save_decomp);
  639. #endif
  640. }
  641.  
  642. /* This takes a string and returns a backslashed form suitable for printing.
  643.    Iff add_quote is true, it'll add "s at the beginning and end.
  644.    Note that this returns a pointer to a static area that is overwritten with
  645.    each call. . .
  646.  */
  647. #ifdef __STDC__
  648. char *
  649. backslash_a_string (char *string, int add_quote)
  650. #else
  651. char *
  652. backslash_a_string (string, add_quote)
  653.      char *string;
  654.      int add_quote;
  655. #endif
  656. {
  657.   char *pf;
  658.   char *pt;
  659.   int ch;
  660.   int size;
  661.   int len;
  662.  
  663.   static char *cbuf;
  664.   static int s_cbuf;
  665.  
  666. #define ALLOC_PT()                \
  667.     len=strlen(pf);                \
  668.     size=pf-string;                \
  669.     if(s_cbuf<3+size+4*len) {        \
  670.         s_cbuf=3+size+4*len;        \
  671.         cbuf= (cbuf) ? ck_realloc(cbuf,s_cbuf) : ck_malloc(s_cbuf); \
  672.     }                    \
  673.     if(size)                \
  674.         bcopy(string,cbuf,size);    \
  675.     pt=cbuf+size;                \
  676.  
  677.  
  678.   pt = 0;
  679.   pf = string;
  680.   if (add_quote)
  681.     {
  682.       ALLOC_PT ()
  683.     * pt++ = '"';
  684.     }
  685.   for (; *pf; pf++)
  686.     {
  687.       ch = *pf;
  688.       if (ch >= ' ' && ch <= '~' && ch != '\\' && (ch != '"' || !add_quote))
  689.     {
  690.       if (pt)
  691.         *pt++ = ch;
  692.       continue;
  693.     }
  694.  
  695.       if (!pt)
  696.     {
  697.       ALLOC_PT ()
  698.     }
  699.       if (ch == '\\')
  700.     {
  701.       *pt++ = '\\';
  702.       *pt++ = '\\';
  703.     }
  704.       else if (ch == '"')
  705.     {
  706.       *pt++ = '\\';
  707.       *pt++ = ch;
  708.     }
  709.       else
  710.     {
  711.       *pt++ = '\\';
  712.       *pt++ = ((ch >> 6) & 0x3) + '0';
  713.       *pt++ = ((ch >> 3) & 0x7) + '0';
  714.       *pt++ = (ch & 0x7) + '0';
  715.     }
  716.     }
  717.   if (add_quote)
  718.     *pt++ = '"';
  719.   if (pt)
  720.     {
  721.       *pt++ = '\0';
  722.       return cbuf;
  723.     }
  724.   return string;
  725. }
  726.  
  727. #ifdef TEST
  728. void
  729. dbg_print_formula (expr)
  730.      unsigned char *expr;
  731. {
  732.   unsigned char byte;
  733.   struct function *f;
  734.   double tmp_flt;
  735.   char *tmp_str;
  736.   long tmp_int;
  737.   struct var *v;
  738.   struct rng rng;
  739.   char *buf;
  740.   unsigned jumpto;
  741.   extern char print_buf[];
  742.   extern char *strcpy ();
  743.  
  744.   if (!expr)
  745.     return;
  746.   strcpy (print_buf, "Formula: ");
  747.   buf = print_buf + 9;
  748.   while (*expr)
  749.     {
  750.       byte = *expr++;
  751.  
  752.       if (byte < USR1)
  753.     f = &the_funs[byte];
  754.       else if (byte < SKIP)
  755.     {
  756.       tmp_int = *expr++;
  757.       f = &usr_funs[byte - USR1][tmp_int];
  758.     }
  759.       else
  760.     f = &skip_funs[byte - SKIP];
  761.  
  762.       if (f->fn_argn & X_J)
  763.     jumpto = *expr++;
  764.       else if (f->fn_argn & X_JL)
  765.     {
  766.       jumpto = expr[0] + ((unsigned) (expr[1]) << 8);
  767.       expr += 2;
  768.     }
  769.       else
  770.     jumpto = 0;
  771.  
  772.       switch (GET_COMP (f->fn_comptype))
  773.     {
  774.     case C_IF:
  775.       sprintf (buf, " if%d.%u", byte, jumpto);
  776.       break;
  777.     case C_ANDOR:
  778.       sprintf (buf, " andor%d.%u", byte, jumpto);
  779.       break;
  780.     case C_ERR:
  781.       tmp_str = (char *) (expr + jumpto);
  782.       byte = *expr++;
  783.       sprintf (buf, " err%d.%p(%s)", byte, tmp_str, tmp_str);
  784.       break;
  785.     case C_FLT:
  786.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_flt, sizeof (double));
  787.       expr += sizeof (double);
  788.       sprintf (buf, " flt.%.15g", tmp_flt);
  789.       break;
  790.     case C_INT:
  791.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_int, sizeof (long));
  792.       expr += sizeof (long);
  793.       sprintf (buf, " int.%ld", tmp_int);
  794.       break;
  795.     case C_STR:
  796.       tmp_str = (char *) (expr + jumpto);
  797.       sprintf (buf, " str.%p.%s", tmp_str, tmp_str);
  798.       break;
  799.     case C_VAR:
  800.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & v, sizeof (struct var *));
  801.       expr += sizeof (struct var *);
  802.       sprintf (buf, " var.%p.%s", v, v->var_name);
  803.       break;
  804.     case C_CELL:
  805.       sprintf (buf, " ref%d.%u.%u", byte, GET_ROW (expr), GET_COL (expr));
  806.       expr += EXP_ADD;
  807.       break;
  808.     case C_RANGE:
  809.       GET_RNG (expr, &rng);
  810.       sprintf (buf, " rng%d.%u-%u,%u-%u", byte, rng.lr, rng.hr, rng.lc, rng.hc);
  811.       expr += EXP_ADD_RNG;
  812.       break;
  813.     case C_FN0:
  814.     case C_FN0X:
  815.     case C_FN1:
  816.     case C_FN2:
  817.     case C_FN3:
  818.     case C_FN4:
  819.     case C_UNA:
  820.     case C_INF:
  821.       sprintf (buf, " fun%d.%s.%p", byte, f->fn_str, f->fn_fun);
  822.       break;
  823.  
  824.     case C_FNN:
  825.       sprintf (buf, " funn%d.%s.%p.%d", byte, f->fn_str, f->fn_fun, *expr++);
  826.       break;
  827.     case C_CONST:
  828.       sprintf (buf, " const%s", f->fn_str);
  829.       break;
  830.     case C_SKIP:
  831.       sprintf (buf, " skip.%d", jumpto);
  832.       break;
  833.     case 0:
  834.       sprintf (buf, " ???%d", byte);
  835.       break;
  836.     default:
  837.       io_error_msg ("Unknown decompile type %d", f->fn_comptype);
  838.     }
  839.       buf += strlen (buf);
  840.     }
  841.   io_text_line (print_buf);
  842. }
  843.  
  844. #endif
  845.